<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
        <textarea style="height: 40%;width: 70%" id="import"></textarea> 
        <button onclick="i()">导入</button>
        <input type="text" name="input" value="" oninput="change()" style="width: 98%;">
        <div id="result"></div>
        <script>
            var normalStrings = ['！','！！','！！！','*','……','？','？？','？？？','技能','技能','技能1','技能2','敏捷','警报','存活','盟友','盟友','弹药','角度','进攻','已进攻','正在进攻','尝试','尝试','平均','躲避','已躲避','正在躲避','后','差','屏蔽','已屏蔽','正在屏蔽','最佳','优秀','加注','加注','阻挡','已阻挡','正在阻挡','蓝色','奖励','奖励','首领','首领','已购买','建造','正在建造','已建造','点燃','正在点燃','已点燃','购买','正在购买','夺取','已夺取','正在夺取','危险','中','接受挑战','魅力','追击','已追击','正在追击','检查点','检查点','云朵','云朵','梅花','梅花','连击','到这儿来','条件','恭喜','连接','已连接','正在连接','建筑','控制点','控制点','冷却时间','冷却时间','腐化','已腐化','正在腐化','货币','货币','严重','蹲下','已蹲下','正在蹲下','当前','当前盟友','当前盟友','当前尝试','当前检查点','当前敌人','当前敌人','当前形态','当前游戏','当前英雄','当前英雄','当前人质','当前人质','当前等级','当前任务','当前对象','当前目标点','当前对象','当前阶段','当前玩家','当前玩家','当前回合','当前目标','当前目标','当前升级','伤害','已伤害','正在伤害','危险','已死亡','发牌','正在发牌','已发牌','牌堆','牌堆','战败','防守','已防守','正在防守','防御','送达','已送达','正在送达','深度','干扰','已干扰','正在干扰','摧毁','已摧毁','正在摧毁','探测','被探测','正在探测','灵巧','方块','方块','死亡','弃牌','已弃牌','正在弃牌','断开','已断开','正在断开','距离','距离','躲闪','已躲闪','正在躲闪','罩子','罩子','下','下载','已下载','正在下载','平局','正在抽牌','已抽牌','掉落','已掉落','正在掉落','正在死亡','东','消灭','已消灭','正在消灭','消灭','消灭','敌人','敌人','进入','护送','已护送','正在护送','优秀','离开','经验值','极端','面向','面向','正在面向','已失败','即将失败','失败','跌落','已跌落','正在跌落','远','快','较快','最快','失误','失误','最终','最终盟友','最终盟友','最终尝试','最终检查点','最终敌人','最终敌人','最终形态','最终游戏','最终英雄','最终英雄','最终人质','最终人质','最终物品','最终等级','最终任务','最终对象','最终目标点','最终对象','最终阶段','最终玩家','最终玩家','最终回合','最终目标','最终目标','最终时间','最终升级','寻找','正在寻找','结束','已结束','正在结束','已飞行','飞行','正在飞行','收起','已收起','正在收起','表格','表格','前','已找到','冰冻','正在冰冻','已冰冻','比赛','比赛','战败场数','胜利场数','GG','前往','终点','终点','正在前往','好','好运','再见','绿色','有罪','入侵','已入侵','正在入侵','手牌','手牌','治疗','已治疗','治疗者','治疗者','正在治疗','红桃','心','高度','问候','求助','此处','英雄','英雄','已隐藏','隐藏','正在隐藏','最高得分','最高得分','击中','正在击中','嗯','人质','人质','哈','狩猎','已狩猎','猎人','猎人','正在狩猎','我放弃了','我尽力了','在视野中','收入','正在前来','初始','初始盟友','初始盟友','初始尝试','初始检查点','初始敌人','初始敌人','初始形态','初始游戏','初始英雄','初始英雄','初始人质','初始等级','初始任务','初始对象','初始目标点','初始对象','初始阶段','初始玩家','初始玩家','初始回合','初始目标','初始目标','初始升级','无罪','内','智力','互动','不可见','物品','物品','加入','已加入','正在加入','跳跃','正在跳跃','击杀','击杀','连杀','连杀','连杀','队长','队长','最少','左','更少','等级','等级下降','等级提升','等级','生命','受限','生命','读取','已读取','正在读取','坐标','锁定','已锁定','正在锁定','败者','败者','失败','失败','较大','轻微','较小','任务','任务','放弃的任务','任务完成','失败的任务','任务','适中','金钱','怪物','怪物','更多','最多','我的错','近','最新高分','最新记录','下一个','下一批盟友','下一个盟友','下一次尝试','下一个检查点','下一批敌人','下一个敌人','下一个表格','下一个游戏','下一个英雄','下一批英雄','下一个人质','下一批人质','下一个等级','下一个任务','下一批对象','下一个目标点','下一个对象','下一个阶段','下一个玩家','下一批玩家','下一个回合','下一个目标','下一批目标','下一个升级','表现不错','否','不用了','无','普通','北','东北','西北','算了吧','对象','目标点','目标点','对象','获取','已获取','正在获取','关闭','开启','噢','啊呀','最佳','优化','已优化','正在优化','不在视野中','正在远去','外','上方','加时','参与者','参与者','运载目标','运载目标','阶段','阶段','选取','已选取','正在选取','堆','堆','打出','已打出','玩家','玩家','正在打出','点','点','获得分数','失去分数','位置','能量','强化','强化','价格','主要攻击模式','飞弹','飞弹','保护','已保护','正在保护','已净化','净化','正在净化','紫色','复活','已复活','正在复活','排名','等级 A','等级 B','等级 C','等级 D','等级 E','等级 F','等级 S','前往','已抵达','正在前往','就绪','记录','记录','恢复','已恢复','正在恢复','红色','剩余','剩余','营救','已营救','正在营救','资源','资源','重生','已重生','正在重生','揭示','已揭示','正在揭示','撤销','已撤销','正在撤销','右','回合','回合','战败回合数','胜利回合数','运行','正在运行','安全','保存','已保存','正在保存','分数','分数','辅助攻击模式','保护','已保护','正在保护','选择','已选择','正在选择','出售','正在出售','服务器负载','服务器负载平均值','服务器负载峰值','撕裂','严重','已撕裂','正在撕裂','商店','商店','洗牌','已洗牌','正在洗牌','击沉','正在击沉','跳过','已跳过','正在跳过','沉睡','正在沉睡','已沉睡','慢','较慢','最慢','已出售','抱歉','南','东南','西南','黑桃','黑桃','火花','孵化','已孵化','正在孵化','速度','速度','球体','球形','稳定','已稳定','正在稳定','存放宠物','星星','群星','开始','已开始','正在开始','状态','停止','走开','已停止','正在停止','阻止','已阻止','正在阻止','力量','昏迷','已昏迷','正在昏迷','次佳','成功','绝杀局','已击沉','强烈','生存','已生存','正在生存','目标','目标','队伍','队友','队友','队伍','极差','衷心感谢','感谢','太棒了','威胁','威胁等级','威胁等级','威胁','绝杀局','时间','时间','总计','交易','已交易','正在交易','叛徒','叛徒','转移','已转移','正在转移','再来试试','炮台','炮台','呃','终极技能','下方','未知','不受限','解锁','已解锁','正在解锁','不安全','不稳定','上','升级','升级','上传','已上传','正在上传','使用技能 1','使用技能 2','使用终极技能','胜利','可见','漩涡','漩涡','等待','正在等待','墙壁','墙壁','警告','欢迎','称赞','西','白色','关键牌','胜利','胜者','胜者','胜利','感知','较差','最差','哇哦','黄色','是','你','你失败了','你胜利了','区域','区域']
            var heroStrings = ['雾子','安娜','艾什','巴蒂斯特','堡垒','布里吉塔','卡西迪','D.Va','末日铁拳','回声','源氏','半藏','渣客女王','狂鼠','卢西奥','美','天使','莫伊拉','奥丽莎','法老之鹰','死神','莱因哈特','路霸','西格玛','索杰恩','士兵：76','黑影','秩序之光','托比昂','猎空','黑百合','温斯顿','破坏球','查莉娅','禅雅塔']
            var concatString = [{val: '-> {0}', format: "字符串(\"$1\", $2)", len: 1},{val: '#{0}', format: "字符串(\"$1\", $2)", len: 1},{val: '({0})', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} ->', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} <-', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} <->', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} 米', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} 米/秒', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}秒', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}！', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}！！', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}！！！', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}%', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}:', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}？', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}？？', format: "字符串(\"$1\", $2)", len: 1},{val: '{0}？？？', format: "字符串(\"$1\", $2)", len: 1},{val: '<- {0}', format: "字符串(\"$1\", $2)", len: 1},{val: '<-> {0}', format: "字符串(\"$1\", $2)", len: 1},{val: '第{0}回合', format: "字符串(\"$1\", $2)", len: 1},{val: '¡{0}!', format: "字符串(\"$1\", $2)", len: 1},{val: '¿{0}?', format: "字符串(\"$1\", $2)", len: 1},{val: '{0} - {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} -> {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} != {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} * {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} / {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} + {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} <- {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} <-> {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} < {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} <= {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} = {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} == {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} > {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} >= {1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0}和{1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0}对阵{1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0}，{1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0}：{1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0}:{1}', format: "字符串(\"$1\", $2, $3)", len: 2},{val: '{0} - {1} - {2}', format: "字符串(\"$1\", $2, $3, $4)", len: 3},{val: '{0} : {1} : {2}', format: "字符串(\"$1\", $2, $3, $4)", len: 3},{val: '{0}，{1}和{2}', format: "字符串(\"$1\", $2, $3, $4)", len: 3},{val: '{0}：{1}和{2}', format: "字符串(\"$1\", $2, $3, $4}", len: 3}]
            var additions = []

            var res0 = {}
            var res1 = {}
                    
            function addString(s, type) {
                if(type == 0) {
                    if(!(s.val in res0) || res0[s.val].code.length > s.code.length)
                        res0[s.val] = s
                } else {
                    if(!(s.val in res1) || res1[s.val].code.length > s.code.length)
                        res1[s.val] = s
                }
            }
            
            function preWork() {
                res0 = {}
                res1 = {}
                for (let ind in additions) addString({val: additions[ind].val, code: additions[ind].code})
                for (let ind in normalStrings) {
                    let str = normalStrings[ind]
                    let obj = {
                        val: str,
                        code: `字符串("${str}")`
                    }
                    addString(obj, 0)
                    let len = str.length
                    for (let sublen = 1;sublen < len;sublen++) 
                        for (let startPos = 0;startPos + sublen <= len;startPos++) {
                            let substr = str.substring(startPos, startPos + sublen)
                            let code = `截取字符串(字符串("${str}"), ${startPos}, ${sublen})`
                            addString({val: substr, code: code}, 0)
                        }
                }
                for (let ind in heroStrings) {
                    let str = heroStrings[ind]
                    let obj = {
                        val: `${str}？`,
                        code: `字符串("{0}？", 英雄(${str}))`
                    }
                    addString(obj, 1)
                    let len = str.length + 1
                    for (let sublen = 1;sublen < len;sublen++) 
                        for (let startPos = 0;startPos + sublen <= len;startPos++) {
                            let substr = str.substring(startPos, startPos + sublen)
                            let code = `截取字符串(字符串("{0}？", 英雄(${str}))), ${startPos}, ${sublen})`
                            addString({val: substr, code: code}, 1)
                        }
                }
                for (let ind in concatString) {
                    let reg = concatString[ind].val
                    reg = reg.replace("(", "\\(").replace(")", "\\)").replace("*", "\\*").replace("+", "\\+")
                    reg = reg.replace("{0}", "(.+)")
                    reg = reg.replace("{1}", "(.+)")
                    reg = reg.replace("{2}", "(.+)")
                    reg = reg.replace(" ", "")
                    concatString[ind].reg = new RegExp(`^${reg}$`)
                }
                let re = []
                for(let x in res0) if(x.length > 0) re.push(res0[x])
                for(let x in res1) if(x.length > 0) if(!(x in res0)) re.push(res1[x])
                return re.sort((x, y) => y.val.length - x.val.length)
            }
            
            let data = preWork()
            let errTag = ""
            
            function convertToString(element) {
                if(typeof(element) == "string") return element
                if(element.length == 1) return element[0]
                if(element.length == 2) return `字符串("{0} {1}", ${element[0]}, ${element[1]})`
                if(element.length == 3) return `字符串("{0} {1} {2}", ${element[0]}, ${element[1]}, ${element[2]})`
                return `字符串("{0} {1} {2}", ${element[0]}, ${element[1]}, ${convertToString(element.slice(2))})`
            }
            
            let cnt = 0
            
            function f(str) {
                cnt++
                if(cnt > 1000) {errTag = "递归次数过多"; return ""}
                if(errTag != "") return ""
                for(let ind in data) {
                    if(str.startsWith(data[ind].val)) {
                        if(data[ind].val == str) return [data[ind].code]
                    }
                }
                for(let ind in concatString) {
                    let concat = concatString[ind]
                    let res = str.match(concat.reg)
                    if(res == null) continue
                    let elements = []
                    for(let i=0;i<concat.len;i++) elements.push(convertToString(f(res[i+1])))
                    if(errTag != "") return ""
                    let ret = concat.format.replace("$1", concat.val)
                    for(let i=0;i<concat.len;i++) ret = ret.replace("$" + (i + 2), elements[i])
                    return ret
                }
                for(let ind in data) {
                    if(str.startsWith(data[ind].val)) {
                        let res = f(str.substring(data[ind].val.length))
                        return [data[ind].code].concat(res)
                    }
                }
                errTag = str.charAt(0)
                return ""
            }
            
            function change() {
                let val = document.getElementsByName("input")[0].value
                errTag = ""
                let res = convertToString(f(val))
                if(errTag == "") document.getElementById("result").textContent = res
                else document.getElementById("result").textContent = `找不到字符：${errTag}`
            }
            
            function i() {
                let text = document.getElementById("import").value
                let lines = text.split("\n")
                additions = []
                for(let ind in lines) {
                    let line = lines[ind]
                    if(line.indexOf("|") == -1) continue
                    line = line.split("|")
                    additions.push({val: line[0], code: line[1]})
                }
                data = preWork()
                console.log(data)
            }
        </script>
    </body>
</html>